<!DOCTYPE html>
<html lang=zh>
<head>
    <meta charset="utf-8">
    
    <title>第四十一章： 基于SpringBoot &amp; RabbitMQ完成DirectExchange分布式消息消费 | 恒宇少年De成长之路</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
    <meta name="description" content="消息队列目前流行的有KafKa、RabbitMQ、ActiveMQ等，它们的诞生无非不是为了解决消息的分布式消费，完成项目、服务之间的解耦动作。消息队列提供者与消费者之间完全采用异步通信方式，极力的提高了系统的响应能力，从而提高系统的网络请求吞吐量。每一种的消息队列都有它在设计上的独一无二的优势，在实际的项目技术选型时根据项目的需求来确定。">
<meta name="keywords" content="SpringBoot">
<meta property="og:type" content="article">
<meta property="og:title" content="第四十一章： 基于SpringBoot &amp; RabbitMQ完成DirectExchange分布式消息消费">
<meta property="og:url" content="http://blog.yuqiyu.com/spring-boot-chapter-41/index.html">
<meta property="og:site_name" content="恒宇少年De成长之路">
<meta property="og:description" content="消息队列目前流行的有KafKa、RabbitMQ、ActiveMQ等，它们的诞生无非不是为了解决消息的分布式消费，完成项目、服务之间的解耦动作。消息队列提供者与消费者之间完全采用异步通信方式，极力的提高了系统的响应能力，从而提高系统的网络请求吞吐量。每一种的消息队列都有它在设计上的独一无二的优势，在实际的项目技术选型时根据项目的需求来确定。">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4461954-482466df12b84fe3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4461954-758240519223899f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:image" content="http://upload-images.jianshu.io/upload_images/4461954-d80b777ca38632ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
<meta property="og:updated_time" content="2018-01-23T15:53:42.494Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="第四十一章： 基于SpringBoot &amp; RabbitMQ完成DirectExchange分布式消息消费">
<meta name="twitter:description" content="消息队列目前流行的有KafKa、RabbitMQ、ActiveMQ等，它们的诞生无非不是为了解决消息的分布式消费，完成项目、服务之间的解耦动作。消息队列提供者与消费者之间完全采用异步通信方式，极力的提高了系统的响应能力，从而提高系统的网络请求吞吐量。每一种的消息队列都有它在设计上的独一无二的优势，在实际的项目技术选型时根据项目的需求来确定。">
<meta name="twitter:image" content="http://upload-images.jianshu.io/upload_images/4461954-482466df12b84fe3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240">
    

    
        <link rel="alternate" href="/" title="恒宇少年De成长之路" type="application/atom+xml" />
    

    

    <link rel="stylesheet" href="/libs/font-awesome/css/font-awesome.min.css">
    <link rel="stylesheet" href="/libs/open-sans/styles.css">
    <link rel="stylesheet" href="/libs/source-code-pro/styles.css">

    <link rel="stylesheet" href="/css/style.css">

    <script src="/libs/jquery/2.1.3/jquery.min.js"></script>
    
    
        <link rel="stylesheet" href="/libs/lightgallery/css/lightgallery.min.css">
    
    
        <link rel="stylesheet" href="/libs/justified-gallery/justifiedGallery.min.css">
    
    
    
    


</head>

<body>
    <div id="container">
        <header id="header">
    <div id="header-main" class="header-inner">
        <div class="outer">
            <a href="/" id="logo">
                <i class="logo"></i>
                <span class="site-title">恒宇少年De成长之路</span>
            </a>
            <nav id="main-nav">
                
                    <a class="main-nav-link" href="/.">首页</a>
                
                    <a class="main-nav-link" href="/archives">时间轴</a>
                
                    <a class="main-nav-link" href="/categories">文章专题</a>
                
                    <a class="main-nav-link" href="/tags">标签云</a>
                
                    <a class="main-nav-link" href="/about">关于我</a>
                
            </nav>
            
                
                <nav id="sub-nav">
                    <div class="profile" id="profile-nav">
                        <a id="profile-anchor" href="javascript:;">
                            <img class="avatar" src="/css/images/avatar.png" />
                            <i class="fa fa-caret-down"></i>
                        </a>
                    </div>
                </nav>
            
            <div id="search-form-wrap">

    <form class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
        <!--button type="submit" class="search-form-submit"></button-->
    </form>
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="想要查找什么..." />
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(未命名)',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
<script src="/js/insight.js"></script>

</div>
        </div>
    </div>
    <div id="main-nav-mobile" class="header-sub header-inner">
        <table class="menu outer">
            <tr>
                
                    <td ><a  class="main-nav-link" href="/.">首页</a></td>
                
                    <td ><a  class="main-nav-link" href="/archives">时间轴</a></td>
                
                    <td ><a  class="main-nav-link" href="/categories">文章专题</a></td>
                
                    <td ><a  class="main-nav-link" href="/tags">标签云</a></td>
                
                    <td ><a  class="main-nav-link" href="/about">关于我</a></td>
                
                <td>
                    
    <div class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
    </div>

                </td>
            </tr>
        </table>
    </div>
</header>

        <div class="outer">
            
                

<aside id="profile">
    <div class="inner profile-inner">
        <div class="base-info profile-block">
            <img id="avatar" src="/css/images/avatar.png" />
            <h2 id="name">恒宇少年</h2>
            <h3 id="title">Java软件工程师 &amp; 程序猿</h3>
            <span id="location"><i class="fa fa-map-marker"></i>山东, 济南</span>
            <a id="follow" target="_blank" href="https://www.jianshu.com/u/092df3f77bca">关注我</a>
        </div>
        <div class="article-info profile-block">
            <div class="article-info-block">
                43
                <span>文章</span>
            </div>
            <div class="article-info-block">
                2
                <span>标签</span>
            </div>
        </div>
        
        <div class="profile-block social-links">
            <table>
                <tr>
                    
                    
                    <td>
                        <a href="http://github.com/ppoffice/hexo-theme-icarus" target="_blank" title="github" class=tooltip>
                            <i class="fa fa-github"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="twitter" class=tooltip>
                            <i class="fa fa-twitter"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="facebook" class=tooltip>
                            <i class="fa fa-facebook"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="dribbble" class=tooltip>
                            <i class="fa fa-dribbble"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="rss" class=tooltip>
                            <i class="fa fa-rss"></i>
                        </a>
                    </td>
                    
                </tr>
            </table>
        </div>
        
    </div>
</aside>

            
            <section id="main"><article id="post-spring-boot-chapter-41" class="article article-type-post" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 class="article-title" itemprop="name">
            第四十一章： 基于SpringBoot &amp; RabbitMQ完成DirectExchange分布式消息消费
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/spring-boot-chapter-41/">
            <time datetime="2017-12-02T16:00:00.000Z" itemprop="datePublished">2017-12-03</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/SpringBoot/">SpringBoot</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>消息队列目前流行的有KafKa、RabbitMQ、ActiveMQ等，它们的诞生无非不是为了解决消息的分布式消费，完成项目、服务之间的解耦动作。消息队列提供者与消费者之间完全采用异步通信方式，极力的提高了系统的响应能力，从而提高系统的网络请求吞吐量。<br>每一种的消息队列都有它在设计上的独一无二的优势，在实际的项目技术选型时根据项目的需求来确定。<br><a id="more"></a></p>
<h1 id="本章目标"><a href="#本章目标" class="headerlink" title="本章目标"></a>本章目标</h1><p>基于<code>SpringBoot</code>项目整合<code>RabbitMQ</code>消息队列，完成<code>DirectExchange（路由键）</code>分布式消息消费。</p>
<h1 id="SpringBoot-企业级核心技术学习专题"><a href="#SpringBoot-企业级核心技术学习专题" class="headerlink" title="SpringBoot 企业级核心技术学习专题"></a>SpringBoot 企业级核心技术学习专题</h1><table>
<thead>
<tr>
<th style="text-align:center">专题</th>
<th style="text-align:left">专题名称</th>
<th style="text-align:left">专题描述</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">001</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/3f69deddbed3" target="_blank" rel="noopener">Spring Boot 核心技术</a></td>
<td style="text-align:left">讲解SpringBoot一些企业级层面的核心组件</td>
</tr>
<tr>
<td style="text-align:center">002</td>
<td style="text-align:left"><a href="https://gitee.com/hengboy/spring-boot-chapter" target="_blank" rel="noopener">Spring Boot 核心技术章节源码</a></td>
<td style="text-align:left">Spring Boot 核心技术简书每一篇文章码云对应源码</td>
</tr>
<tr>
<td style="text-align:center">003</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/1faac22666e7" target="_blank" rel="noopener">Spring Cloud 核心技术</a></td>
<td style="text-align:left">对Spring Cloud核心技术全面讲解</td>
</tr>
<tr>
<td style="text-align:center">004</td>
<td style="text-align:left"><a href="https://gitee.com/hengboy/spring-cloud-chapter" target="_blank" rel="noopener">Spring Cloud 核心技术章节源码</a></td>
<td style="text-align:left">Spring Cloud 核心技术简书每一篇文章对应源码</td>
</tr>
<tr>
<td style="text-align:center">005</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/ab4789177827" target="_blank" rel="noopener">QueryDSL 核心技术</a></td>
<td style="text-align:left">全面讲解QueryDSL核心技术以及基于SpringBoot整合SpringDataJPA</td>
</tr>
<tr>
<td style="text-align:center">006</td>
<td style="text-align:left"><a href="http://www.jianshu.com/c/f1b269bb2fd6" target="_blank" rel="noopener">SpringDataJPA 核心技术</a></td>
<td style="text-align:left">全面讲解SpringDataJPA核心技术</td>
</tr>
</tbody>
</table>
<h1 id="Exchange"><a href="#Exchange" class="headerlink" title="Exchange"></a>Exchange</h1><p>在<code>RabbitMQ</code>中有三种常用的转发方式，分别是：</p>
<p><code>DirectExchange</code>：路由键方式转发消息。<br><code>FanoutExchange</code>：广播方式转发消息。<br><code>TopicExchange</code>：主题匹配方式转发消息。</p>
<p>我们本章先来讲解<code>DirectExchange</code>路由键方式，根据设置的路由键的值进行完全匹配时转发，下面我们来看一张图，形象的介绍了转发消息匹配流程，如下图所示：<br><img src="http://upload-images.jianshu.io/upload_images/4461954-482466df12b84fe3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="DirectExchange"></p>
<p>我们可以看到上图，当消息被提供者发送到<code>RabbitMQ</code>后，会根据配置队列的交换以及绑定实例进行转发消息，上图只会将消息转发路由键为<code>KEY</code>的队列消费者对应的实现方法逻辑中，从而完成消息的消费过程。</p>
<h2 id="安装RabbitMQ"><a href="#安装RabbitMQ" class="headerlink" title="安装RabbitMQ"></a>安装RabbitMQ</h2><p>因为<code>RabbitMQ</code>是跨平台的分布式消息队列服务，可以部署在任意的操作系统上，下面我们分别介绍在不同的系统下该怎么去安装<code>RabbitMQ</code>服务。</p>
<p>我们本章采用的环境版本如下：</p>
<ul>
<li>RabbitMQ Server 3.6.14</li>
<li>Erlang/OTP_X64 20.1</li>
</ul>
<h3 id="Windows下安装"><a href="#Windows下安装" class="headerlink" title="Windows下安装"></a>Windows下安装</h3><p>我们先去<code>RabbitMQ</code>官方网站下载最新版的安装包，下载地址：<code>https://www.rabbitmq.com/download.html</code>，可以根据不同的操作系统选择下载。<br>我们在安装<code>RabbitMQ</code>服务端时需要<code>Erlang</code>环境的支持，所以我们需要先安装<code>Erlang</code>。</p>
<ol>
<li><p>我们通过<code>Erlang</code>官方网站<code>http://www.erlang.org/downloads</code>下载最新的安装包</p>
</li>
<li><p>我们访问<code>RabiitmQ</code>官方下载地址<code>https://www.rabbitmq.com/download.html</code>下载最新安装包。</p>
</li>
</ol>
<blockquote>
<p>因为是国外的网站所以下载比较慢，大家下载时会浪费时间，我已经将安装包分享到了百度网盘，下载地址：<a href="https://pan.baidu.com/s/1pLkNXWn" target="_blank" rel="noopener">安装包下载地址</a>，密码：<code>pexf</code></p>
</blockquote>
<ol>
<li><p>运行安装<code>Erlang</code></p>
</li>
<li><p>运行安装<code>RabbitMQ</code></p>
</li>
</ol>
<p>5.检查服务是否安装完成，<code>RabbitMQ</code>安装完成后会以服务的形式创建，并且随着开机启动，如下所示：<br><img src="http://upload-images.jianshu.io/upload_images/4461954-758240519223899f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="Rabbit服务"></p>
<h3 id="Mac-OS-X-安装"><a href="#Mac-OS-X-安装" class="headerlink" title="Mac OS X 安装"></a>Mac OS X 安装</h3><p>在Mac OS X中我们使用<code>brew</code>工具可以很简单的安装<code>RabbitMQ</code>服务端，步骤如下：</p>
<ol>
<li><code>brew</code>更新到最新版本，执行：<code>brew update</code></li>
<li>接下来我们安装<code>Erlang</code>，执行：<code>brew install erlang</code></li>
<li>最后安装<code>RabbitMQ</code>，执行：<code>brew install rabbitmq</code></li>
</ol>
<p>我们通过上面的步骤安装后，<code>RabbitMQ</code>会被自动安装到<code>/usr/local/Cellar/rabbitmq/</code>目录下，下面我们进入<code>cd sbin</code>目录执行：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo ./rabbitmq-server</span><br></pre></td></tr></table></figure></p>
<p>可以直接启动<code>RabbitMQ</code>服务。</p>
<h3 id="Ubuntu-安装"><a href="#Ubuntu-安装" class="headerlink" title="Ubuntu 安装"></a>Ubuntu 安装</h3><p>在<code>Ubuntu</code>操作系统中，我们可以直接使用<code>APT</code>仓库进行安装，我使用的系统版本是<code>16.04</code>，系统版本并不影响安装。</p>
<ol>
<li>安装<code>Erlang</code>，执行命令：<code>sudo apt-get install erlang</code></li>
<li><p>下面我们需要将<code>RabbitMQ</code>的安装源配置信息写入到系统的<code>/etc/apt/sources.list.d</code>配置文件内，执行如下命令：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo &apos;deb http://www.rabbitmq.com/debian/ testing main&apos; | sudo tee /etc/apt/sources.list.d/rabbitmq.list</span><br></pre></td></tr></table></figure>
</li>
<li><p>下面我们更新<code>APT</code>本地仓库的安装包列表，执行命令：<code>sudo apt-get update</code></p>
</li>
<li>最后安装<code>RabbitMQ</code>服务，执行命令：<code>sudo apt-get install rabbitmq-server</code></li>
</ol>
<h2 id="启用界面管理插件"><a href="#启用界面管理插件" class="headerlink" title="启用界面管理插件"></a>启用界面管理插件</h2><p><code>RabbitMQ</code>提供了界面管理的<code>web</code>插件，我们只需要启用指定的插件就可以了，下面我们来看看<code>Windows</code>操作系统下该怎么启动界面管理插件。<br>我们使用<code>CMD</code>进入<code>RabbitMQ</code>安装目录<code>C:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.14</code>，然后我们进入<code>sbin</code>目录，可以看到目录内存在很多个<code>bat</code>脚本程序，我们找到<code>rabbitmq-plugins.bat</code>，这个脚本程序可以控制<code>RabbitMQ</code>插件启用禁用，我们执行如下脚本命令来启用界面管理插件：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rabbitmq-plugins.bat enable rabbitmq_management</span><br></pre></td></tr></table></figure></p>
<p>命令行输出内容如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">The following plugins have been enabled:</span><br><span class="line">  amqp_client</span><br><span class="line">  cowlib</span><br><span class="line">  cowboy</span><br><span class="line">  rabbitmq_web_dispatch</span><br><span class="line">  rabbitmq_management_agent</span><br><span class="line">  rabbitmq_management</span><br><span class="line"></span><br><span class="line">Applying plugin configuration to rabbit@yuqiyu... started 6 plugins.</span><br></pre></td></tr></table></figure></p>
<p>可以看到输出的内容<code>RabbitMQ</code>自动启动了6个插件，我们现在访问<a href="http://127.0.0.1:15672" target="_blank" rel="noopener">http://127.0.0.1:15672</a>地址可以直接打开<code>RabbitMQ</code>的界面管理平台，而默认的用户名/密码分别为：<code>guest/guest</code>，通过该用户可以直接登录管理平台。</p>
<h3 id="禁用界面管理插件"><a href="#禁用界面管理插件" class="headerlink" title="禁用界面管理插件"></a>禁用界面管理插件</h3><p>我们同样可以禁用<code>RabbitMQ</code>指定插件，执行如下命令：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rabbitmq-plugins.bat disable rabbitmq_management</span><br></pre></td></tr></table></figure></p>
<p>命令创建输出内容则是相关停止插件的日志，如下：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">The following plugins have been disabled:</span><br><span class="line">  amqp_client</span><br><span class="line">  cowlib</span><br><span class="line">  cowboy</span><br><span class="line">  rabbitmq_web_dispatch</span><br><span class="line">  rabbitmq_management_agent</span><br><span class="line">  rabbitmq_management</span><br><span class="line"></span><br><span class="line">Applying plugin configuration to rabbit@yuqiyu... stopped 6 plugins.</span><br></pre></td></tr></table></figure></p>
<p>这样我们再访问<a href="http://127.0.0.1:15672" target="_blank" rel="noopener">http://127.0.0.1:15672</a>就会发现我们无法访问到界面。</p>
<h1 id="构建项目"><a href="#构建项目" class="headerlink" title="构建项目"></a>构建项目</h1><p>我们使用<code>idea</code>开发工具创建一个<code>SpringBoot</code>项目，添加依赖，pom.xml配置文件如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependencies&gt;</span><br><span class="line">        &lt;!--rabbitmq依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-amqp&lt;/artifactId&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--web依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--lombok依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;lombok&lt;/artifactId&gt;</span><br><span class="line">            &lt;optional&gt;true&lt;/optional&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--fastjson依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;fastjson&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;1.2.40&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--测试依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;</span><br><span class="line">            &lt;scope&gt;test&lt;/scope&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br></pre></td></tr></table></figure></p>
<p>我们本章来模拟用户注册完成后，将注册用户的编号通过<code>Provider</code>模块发送到<code>RabbitMQ</code>，然后<code>RabbitMQ</code>根据配置的<code>DirectExchange</code>的路由键进行异步转发。</p>
<h4 id="初始化用户表"><a href="#初始化用户表" class="headerlink" title="初始化用户表"></a>初始化用户表</h4><p>下面我们先来创建所需要的<code>用户基本信息表</code>，建表SQL如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE `user_info` (</span><br><span class="line">  `UI_ID` int(11) DEFAULT NULL COMMENT &apos;用户编号&apos;,</span><br><span class="line">  `UI_USER_NAME` varchar(20) DEFAULT NULL COMMENT &apos;用户名称&apos;,</span><br><span class="line">  `UI_NAME` varchar(20) DEFAULT NULL COMMENT &apos;真实姓名&apos;,</span><br><span class="line">  `UI_AGE` int(11) DEFAULT NULL COMMENT &apos;用户年龄&apos;,</span><br><span class="line">  `UI_BALANCE` decimal(10,0) DEFAULT NULL COMMENT &apos;用户余额&apos;</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=&apos;用户基本信息表&apos;;</span><br></pre></td></tr></table></figure></p>
<h3 id="构建-rabbitmq-provider-项目"><a href="#构建-rabbitmq-provider-项目" class="headerlink" title="构建 rabbitmq-provider 项目"></a>构建 rabbitmq-provider 项目</h3><p>基于我们上述的项目创建一个<code>Maven</code>子模块，命名为：<code>rabbitmq-provider</code>，因为是直接创建的<code>Module</code>项目，<code>IDEA</code>并没有给我创建<code>SpringApplication</code>启用类。</p>
<h5 id="创建入口类"><a href="#创建入口类" class="headerlink" title="创建入口类"></a>创建入口类</h5><p>下面我们自行创建一个<code>Provider</code>项目启动入口程序，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 消息队列消息提供者启动入口</span><br><span class="line"> * ========================</span><br><span class="line"> *</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：14:14</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@SpringBootApplication</span><br><span class="line">public class RabbitmqProviderApplication</span><br><span class="line">&#123;</span><br><span class="line">    static Logger logger = LoggerFactory.getLogger(RabbitmqProviderApplication.class);</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 消息队列提供者启动入口</span><br><span class="line">     * @param args</span><br><span class="line">     */</span><br><span class="line">    public static void main(String[] args)</span><br><span class="line">    &#123;</span><br><span class="line">        SpringApplication.run(RabbitmqProviderApplication.class,args);</span><br><span class="line"></span><br><span class="line">        logger.info(&quot;【【【【【消息队列-消息提供者启动成功.】】】】】&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h5 id="application-properties配置文件"><a href="#application-properties配置文件" class="headerlink" title="application.properties配置文件"></a>application.properties配置文件</h5><p>下面我们在<code>src/main/resource</code>目录下创建<code>application.properties</code>并将对应<code>RabbitMQ</code>以及<code>Druid</code>的配置加入，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">#用户名</span><br><span class="line">spring.rabbitmq.username=guest</span><br><span class="line">#密码</span><br><span class="line">spring.rabbitmq.password=guest</span><br><span class="line">#服务器ip</span><br><span class="line">spring.rabbitmq.host=localhost</span><br><span class="line">#虚拟空间地址</span><br><span class="line">spring.rabbitmq.virtual-host=/</span><br><span class="line">#端口号</span><br><span class="line">spring.rabbitmq.port=5672</span><br><span class="line">#配置发布消息确认回调</span><br><span class="line">spring.rabbitmq.publisher-confirms=true</span><br><span class="line"></span><br><span class="line">#数据源配置</span><br><span class="line">spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver</span><br><span class="line">spring.datasource.druid.url=jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true</span><br><span class="line">spring.datasource.druid.username=root</span><br><span class="line">spring.datasource.druid.password=123456</span><br></pre></td></tr></table></figure></p>
<p>在<code>RabbitMQ</code>内有个<code>virtual-host</code>即虚拟主机的概念，一个<code>RabbitMQ</code>服务可以配置多个虚拟主机，每一个虚拟机主机之间是相互隔离，相互独立的，授权用户到指定的<code>virtual-host</code>就可以发送消息到指定队列。</p>
<h5 id="用户实体"><a href="#用户实体" class="headerlink" title="用户实体"></a>用户实体</h5><p>本章数据库操作采用<code>spring-data-jpa</code>，相关文章请访问：<a href="http://www.jianshu.com/p/9d5bf0e4943f" target="_blank" rel="noopener">第十三章：SpringBoot实战SpringDataJPA</a>，我们基于<code>user_info</code>数据表对应创建实体，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">@Data</span><br><span class="line">@Table(name = &quot;user_info&quot;)</span><br><span class="line">@Entity</span><br><span class="line">public class UserEntity</span><br><span class="line">    implements Serializable</span><br><span class="line">&#123;</span><br><span class="line">    /**</span><br><span class="line">     * 用户编号</span><br><span class="line">     */</span><br><span class="line">    @Id</span><br><span class="line">    @GeneratedValue</span><br><span class="line">    @Column(name = &quot;UI_ID&quot;)</span><br><span class="line">    private Long id;</span><br><span class="line">    /**</span><br><span class="line">     * 用户名称</span><br><span class="line">     */</span><br><span class="line">    @Column(name = &quot;UI_USER_NAME&quot;)</span><br><span class="line">    private String userName;</span><br><span class="line">    /**</span><br><span class="line">     * 姓名</span><br><span class="line">     */</span><br><span class="line">    @Column(name = &quot;UI_NAME&quot;)</span><br><span class="line">    private String name;</span><br><span class="line">    /**</span><br><span class="line">     * 年龄</span><br><span class="line">     */</span><br><span class="line">    @Column(name = &quot;UI_AGE&quot;)</span><br><span class="line">    private int age;</span><br><span class="line">    /**</span><br><span class="line">     * 余额</span><br><span class="line">     */</span><br><span class="line">    @Column(name = &quot;UI_BALANCE&quot;)</span><br><span class="line">    private BigDecimal balance;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h5 id="用户数据接口"><a href="#用户数据接口" class="headerlink" title="用户数据接口"></a>用户数据接口</h5><p>创建<code>UserRepository</code>用户数据操作接口，并继承<code>JpaRepository</code>获得<code>spring-data-jpa</code>相关的接口定义方法。如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 用户数据接口定义</span><br><span class="line"> * ========================</span><br><span class="line"> *</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：14:35</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">public interface UserRepository</span><br><span class="line">    extends JpaRepository&lt;UserEntity,Long&gt;</span><br><span class="line">&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h5 id="用户业务逻辑实现"><a href="#用户业务逻辑实现" class="headerlink" title="用户业务逻辑实现"></a>用户业务逻辑实现</h5><p>本章只是简单完成了数据的添加，代码如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 用户业务逻辑实现类</span><br><span class="line"> * ========================</span><br><span class="line"> *</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：14:37</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@Service</span><br><span class="line">@Transactional(rollbackFor = Exception.class)</span><br><span class="line">public class UserService</span><br><span class="line">&#123;</span><br><span class="line">    @Autowired</span><br><span class="line">    private UserRepository userRepository;</span><br><span class="line">    /**</span><br><span class="line">     * 消息队列业务逻辑实现</span><br><span class="line">     */</span><br><span class="line">    @Autowired</span><br><span class="line">    private QueueMessageService queueMessageService;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 保存用户</span><br><span class="line">     * 并写入消息队列</span><br><span class="line">     * @param userEntity</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    public Long save(UserEntity userEntity) throws Exception</span><br><span class="line">    &#123;</span><br><span class="line">        /**</span><br><span class="line">         * 保存用户</span><br><span class="line">         */</span><br><span class="line">        userRepository.save(userEntity);</span><br><span class="line">        /**</span><br><span class="line">         * 将消息写入消息队列</span><br><span class="line">         */</span><br><span class="line">        queueMessageService.send(userEntity.getId(), ExchangeEnum.USER_REGISTER, QueueEnum.USER_REGISTER);</span><br><span class="line"></span><br><span class="line">        return userEntity.getId();</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></p>
<p>在上面业务逻辑实现类内出现了一个名为<code>QueueMessageService</code>消息队列实现类，该类是我们定义的用于发送消息到消息队列的统一入口，在下面我们会详细讲解。</p>
<h5 id="用户控制器"><a href="#用户控制器" class="headerlink" title="用户控制器"></a>用户控制器</h5><p>创建一个名为<code>UserController</code>的控制器类，对应编写一个添加用户的请求方法，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 用户控制器</span><br><span class="line"> * ========================</span><br><span class="line"> *</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：14:41</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@RestController</span><br><span class="line">@RequestMapping(value = &quot;/user&quot;)</span><br><span class="line">public class UserController</span><br><span class="line">&#123;</span><br><span class="line">    /**</span><br><span class="line">     * 用户业务逻辑</span><br><span class="line">     */</span><br><span class="line">    @Autowired</span><br><span class="line">    private UserService userService;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 保存用户基本信息</span><br><span class="line">     * @param userEntity</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @RequestMapping(value = &quot;/save&quot;)</span><br><span class="line">    public UserEntity save(UserEntity userEntity) throws Exception</span><br><span class="line">    &#123;</span><br><span class="line">        userService.save(userEntity);</span><br><span class="line">        return userEntity;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>到这我们添加用户的流程已经编写完成了，那么我们就来看下消息队列<code>QueueMessageService</code>接口的定义以及实现类的定义。</p>
<h5 id="消息队列方法定义接口"><a href="#消息队列方法定义接口" class="headerlink" title="消息队列方法定义接口"></a>消息队列方法定义接口</h5><p>创建一个名为<code>QueueMessageService</code>的接口并且继承了<code>RabbitTemplate.ConfirmCallback</code>接口，而<code>RabbitTemplate.ConfirmCallback</code>接口是用来回调消息发送成功后的方法，当一个消息被成功写入到<code>RabbitMQ</code>服务端时，就会自动的回调<code>RabbitTemplate.ConfirmCallback</code>接口内的<code>confirm</code>方法完成通知，<code>QueueMessageService</code>接口如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 消息队列业务</span><br><span class="line"> * ========================</span><br><span class="line"> *</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：14:50</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">public interface QueueMessageService</span><br><span class="line">    extends RabbitTemplate.ConfirmCallback</span><br><span class="line">&#123;</span><br><span class="line">    /**</span><br><span class="line">     * 发送消息到rabbitmq消息队列</span><br><span class="line">     * @param message 消息内容</span><br><span class="line">     * @param exchangeEnum 交换配置枚举</span><br><span class="line">     * @param queueEnum 队列配置枚举</span><br><span class="line">     * @throws Exception</span><br><span class="line">     */</span><br><span class="line">    public void send(Object message, ExchangeEnum exchangeEnum, QueueEnum queueEnum) throws Exception;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>接下来我们需要实现该接口内的所有方法，并做出一些业务逻辑的处理。</p>
<h5 id="消息队列业务实现"><a href="#消息队列业务实现" class="headerlink" title="消息队列业务实现"></a>消息队列业务实现</h5><p>创建名为<code>QueueMessageServiceSupport</code>实体类实现<code>QueueMessageService</code>接口，并实现接口内的所有方法，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 消息队列业务逻辑实现</span><br><span class="line"> * ========================</span><br><span class="line"> *</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：14:52</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@Component</span><br><span class="line">public class QueueMessageServiceSupport</span><br><span class="line">    implements QueueMessageService</span><br><span class="line">&#123;</span><br><span class="line">    /**</span><br><span class="line">     * 消息队列模板</span><br><span class="line">     */</span><br><span class="line">    @Autowired</span><br><span class="line">    private RabbitTemplate rabbitTemplate;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public void send(Object message, ExchangeEnum exchangeEnum, QueueEnum queueEnum) throws Exception &#123;</span><br><span class="line">        //设置回调为当前类对象</span><br><span class="line">        rabbitTemplate.setConfirmCallback(this);</span><br><span class="line">        //构建回调id为uuid</span><br><span class="line">        CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());</span><br><span class="line">        //发送消息到消息队列</span><br><span class="line">        rabbitTemplate.convertAndSend(exchangeEnum.getValue(),queueEnum.getRoutingKey(),message,correlationId);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 消息回调确认方法</span><br><span class="line">     * @param correlationData 请求数据对象</span><br><span class="line">     * @param ack 是否发送成功</span><br><span class="line">     * @param cause</span><br><span class="line">     */</span><br><span class="line">    @Override</span><br><span class="line">    public void confirm(CorrelationData correlationData, boolean ack, String cause) &#123;</span><br><span class="line">        System.out.println(&quot; 回调id:&quot; + correlationData.getId());</span><br><span class="line">        if (ack) &#123;</span><br><span class="line">            System.out.println(&quot;消息发送成功&quot;);</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            System.out.println(&quot;消息发送失败:&quot; + cause);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p><code>convertAndSend</code>方法用于将<code>Object</code>类型的消息转换后发送到<code>RabbitMQ</code>服务端，发送是的消息类型要与消息消费者方法参数保持一致。</p>
<p>在<code>confirm</code>方法内，我们仅仅打印了消息发送时的<code>id</code>，根据<code>ack</code>参数输出消息发送状态。</p>
<blockquote>
<p>在上面代码中我们注入了<code>RabbitTemplate</code>消息队列模板实例，而通过该实例我们可以将消息发送到<code>RabbitMQ</code>服务端。那么这个实例具体在什么地方定义的呢？我们带着这个疑问来创建下面的模块，我们需要将<code>RabbitMQ</code>相关的配置抽取出来作为一个单独的<code>Module</code>存在。</p>
</blockquote>
<h3 id="构建-rabbitmq-common-项目"><a href="#构建-rabbitmq-common-项目" class="headerlink" title="构建 rabbitmq-common 项目"></a>构建 rabbitmq-common 项目</h3><p>该模块项目很简单，只是添加<code>RabbitMQ</code>相关的配置信息，由于<code>Module</code>是一个子模块所以继承了<code>parent</code>所有的依赖，当然我们用到的<code>RabbitMQ</code>相关依赖也不例外。</p>
<h5 id="配置rabbitmq"><a href="#配置rabbitmq" class="headerlink" title="配置rabbitmq"></a>配置rabbitmq</h5><p>在创建配置类之前，我们先来定义两个枚举，分别存放了队列的交换信息、队列路由信息，</p>
<ul>
<li><p>ExchangeEnum (存放了队列交换配置信息)</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * rabbitmq交换配置枚举</span><br><span class="line"> * ========================</span><br><span class="line"> *</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：13:56</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@Getter</span><br><span class="line">public enum ExchangeEnum</span><br><span class="line">&#123;</span><br><span class="line">    /**</span><br><span class="line">     * 用户注册交换配置枚举</span><br><span class="line">     */</span><br><span class="line">    USER_REGISTER(&quot;user.register.topic.exchange&quot;)</span><br><span class="line">    ;</span><br><span class="line">    private String value;</span><br><span class="line"></span><br><span class="line">    ExchangeEnum(String value) &#123;</span><br><span class="line">        this.value = value;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>QueueEnum (存放了队列信息以及队列的路由配置信息)</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 队列配置枚举</span><br><span class="line"> * ========================</span><br><span class="line"> *</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：14:05</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@Getter</span><br><span class="line">public enum QueueEnum</span><br><span class="line">&#123;</span><br><span class="line">    /**</span><br><span class="line">     * 用户注册枚举</span><br><span class="line">     */</span><br><span class="line">    USER_REGISTER(&quot;user.register.queue&quot;,&quot;user.register&quot;)</span><br><span class="line">    ;</span><br><span class="line">    /**</span><br><span class="line">     * 队列名称</span><br><span class="line">     */</span><br><span class="line">    private String name;</span><br><span class="line">    /**</span><br><span class="line">     * 队列路由键</span><br><span class="line">     */</span><br><span class="line">    private String routingKey;</span><br><span class="line"></span><br><span class="line">    QueueEnum(String name, String routingKey) &#123;</span><br><span class="line">        this.name = name;</span><br><span class="line">        this.routingKey = routingKey;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>创建名为<code>UserRegisterQueueConfiguration</code>的实体类用于配置本章用到的用户注册队列信息，如果你得项目中使用多个队列，建议每一个业务逻辑创建一个配置类，分开维护，这样不容易出错。配置信息如下：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 用户注册消息队列配置</span><br><span class="line"> * ========================</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：16:58</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@Configuration</span><br><span class="line">public class UserRegisterQueueConfiguration &#123;</span><br><span class="line">    /**</span><br><span class="line">     * 配置路由交换对象实例</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @Bean</span><br><span class="line">    public DirectExchange userRegisterDirectExchange()</span><br><span class="line">    &#123;</span><br><span class="line">        return new DirectExchange(ExchangeEnum.USER_REGISTER.getValue());</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 配置用户注册队列对象实例</span><br><span class="line">     * 并设置持久化队列</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @Bean</span><br><span class="line">    public Queue userRegisterQueue()</span><br><span class="line">    &#123;</span><br><span class="line">        return new Queue(QueueEnum.USER_REGISTER.getName(),true);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 将用户注册队列绑定到路由交换配置上并设置指定路由键进行转发</span><br><span class="line">     * @return</span><br><span class="line">     */</span><br><span class="line">    @Bean</span><br><span class="line">    public Binding userRegisterBinding()</span><br><span class="line">    &#123;</span><br><span class="line">        return BindingBuilder.bind(userRegisterQueue()).to(userRegisterDirectExchange()).with(QueueEnum.USER_REGISTER.getRoutingKey());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>该配置类大致分为如下三部分：</p>
<ul>
<li><p>配置交换实例<br>配置<code>DirectExchange</code>实例对象，为交换设置一个名称，引用<code>ExchangeEnum</code>枚举配置的交换名称，消息提供者与消息消费者的交换名称必须一致才具备的第一步的通讯基础。</p>
</li>
<li><p>配置队列实例<br>配置<code>Queue</code>实例对象，为消息队列设置一个名称，引用<code>QueueEnum</code>枚举配置的队列名称，当然队列的名称同样也是提供者与消费者之间的通讯基础。</p>
</li>
<li><p>绑定队列实例到交换实例<br>配置<code>Binding</code>实例对象，消息绑定的目的就是将<code>Queue</code>实例绑定到<code>Exchange</code>上，并且通过设置的路由<code>Key</code>进行消息转发，配置了路由<code>Key</code>后，只有符合该路由配置的消息才会被转发到绑定交换上的消息队列。</p>
</li>
</ul>
<p>我们的<code>rabbitmq-common</code>模块已经编写完成。</p>
<h5 id="添加-rabbitmq-provider-依赖-rabbitmq-common"><a href="#添加-rabbitmq-provider-依赖-rabbitmq-common" class="headerlink" title="添加 rabbitmq-provider 依赖 rabbitmq-common"></a>添加 rabbitmq-provider 依赖 rabbitmq-common</h5><p>下面我们回到<code>rabbitmq-provider</code>模块，修改pom.xml配置文件，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&lt;dependencies&gt;</span><br><span class="line">        &lt;!--添加common模块依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;com.hengyu&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;rabbitmq-common&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--mysql依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;mysql&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--druid数据源依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;com.alibaba&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;druid-spring-boot-starter&lt;/artifactId&gt;</span><br><span class="line">            &lt;version&gt;1.1.5&lt;/version&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">        &lt;!--data jpa依赖--&gt;</span><br><span class="line">        &lt;dependency&gt;</span><br><span class="line">            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</span><br><span class="line">            &lt;artifactId&gt;spring-boot-starter-data-jpa&lt;/artifactId&gt;</span><br><span class="line">        &lt;/dependency&gt;</span><br><span class="line">    &lt;/dependencies&gt;</span><br></pre></td></tr></table></figure></p>
<p>可以看到我们将<code>rabbitmq-common</code>模块添加到了<code>rabbitmq-provider</code>模块的<code>pom</code>配置文件内，完成了模块之间的相互依赖，这样我们<code>rabbitmq-provider</code>就自动添加了对应的消息队列配置。</p>
<h3 id="构建rabbitmq-consumer"><a href="#构建rabbitmq-consumer" class="headerlink" title="构建rabbitmq-consumer"></a>构建rabbitmq-consumer</h3><p>我们再来创建一个<code>rabbitmq-consumer</code>队列消息消费者模块，用于接受消费用户注册消息。</p>
<h5 id="创建入口类-1"><a href="#创建入口类-1" class="headerlink" title="创建入口类"></a>创建入口类</h5><p>同样我们先来创建一个<code>SpringApplication</code>入口启动类，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 消息队列消息消费者入口</span><br><span class="line"> * ========================</span><br><span class="line"> *</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：15:15</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@SpringBootApplication</span><br><span class="line">public class RabbitmqConsumerApplication</span><br><span class="line">&#123;</span><br><span class="line">    static Logger logger = LoggerFactory.getLogger(RabbitmqConsumerApplication.class);</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * rabbitmq消费者启动入口</span><br><span class="line">     * @param args</span><br><span class="line">     */</span><br><span class="line">    public static void main(String[] args)</span><br><span class="line">    &#123;</span><br><span class="line">        SpringApplication.run(RabbitmqConsumerApplication.class,args);</span><br><span class="line"></span><br><span class="line">        logger.info(&quot;【【【【【消息队列-消息消费者启动成功.】】】】】&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<h5 id="application-properties配置文件-1"><a href="#application-properties配置文件-1" class="headerlink" title="application.properties配置文件"></a>application.properties配置文件</h5><p>配置文件的消息队列配置信息要与<code>rabbitmq-provider</code>配置文件一致，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">spring.application.name=rabbitmq-consumer</span><br><span class="line">#启动端口</span><br><span class="line">server.port=1111</span><br><span class="line">#用户名</span><br><span class="line">spring.rabbitmq.username=guest</span><br><span class="line">#密码</span><br><span class="line">spring.rabbitmq.password=guest</span><br><span class="line">#服务器ip</span><br><span class="line">spring.rabbitmq.host=localhost</span><br><span class="line">#虚拟空间地址</span><br><span class="line">spring.rabbitmq.virtual-host=/</span><br><span class="line">#端口号</span><br><span class="line">spring.rabbitmq.port=5672</span><br><span class="line">#配置发布消息确认回调</span><br><span class="line">spring.rabbitmq.publisher-confirms=true</span><br></pre></td></tr></table></figure></p>
<p>我们修改了程序启动的端口号，为了我们下面进行测试的时候不出现端口占用的情况。</p>
<blockquote>
<p>如果<code>RabbitMQ</code>配置信息与<code>rabbitmq-provider</code>不一致，就不会收到消费消息。</p>
</blockquote>
<h5 id="用户注册消息消费者"><a href="#用户注册消息消费者" class="headerlink" title="用户注册消息消费者"></a>用户注册消息消费者</h5><p>创建名为<code>UserConsumer</code>类，用于完成消息监听，并且实现消息消费，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 用户注册消息消费者</span><br><span class="line"> * ========================</span><br><span class="line"> *</span><br><span class="line"> * @author 恒宇少年</span><br><span class="line"> * Created with IntelliJ IDEA.</span><br><span class="line"> * Date：2017/11/26</span><br><span class="line"> * Time：15:20</span><br><span class="line"> * 码云：http://git.oschina.net/jnyqy</span><br><span class="line"> * ========================</span><br><span class="line"> */</span><br><span class="line">@Component</span><br><span class="line">@RabbitListener(queues = &quot;user.register.queue&quot;)</span><br><span class="line">public class UserConsumer &#123;</span><br><span class="line"></span><br><span class="line">    @RabbitHandler</span><br><span class="line">    public void execute(Long userId)</span><br><span class="line">    &#123;</span><br><span class="line">        System.out.println(&quot;用户：&quot; + userId+&quot;，完成了注册&quot;);</span><br><span class="line"></span><br><span class="line">        //...//自行业务逻辑处理</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>在消息消费者类内，有两个陌生的注解：</p>
<ul>
<li>@RabbitListener<br><code>RabbitMQ</code>队列消息监听注解，该注解配置监听<code>queues</code>内的队列名称列表，可以配置多个。队列名称对应本章<code>rabbitmq-common</code>模块内<code>QueueEnum</code>枚举<code>name</code>属性。</li>
<li>@RabbitHandler<br><code>RabbitMQ</code>消息处理方法，该方法的参数要与<code>rabbitmq-provider</code>发送消息时的类型保持一致，否则无法自动调用消费方法，也就无法完成消息的消费。</li>
</ul>
<p>#运行测试<br>我们接下来在<code>rabbitmq-provider</code>模块<code>src/test/java</code>下创建一个测试用例，访问用户注册控制器请求路径，如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">@RunWith(SpringRunner.class)</span><br><span class="line">@SpringBootTest(classes = RabbitmqProviderApplication.class)</span><br><span class="line">public class UserTester</span><br><span class="line">&#123;</span><br><span class="line">    /**</span><br><span class="line">     * 模拟mvc测试对象</span><br><span class="line">     */</span><br><span class="line">    private MockMvc mockMvc;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * web项目上下文</span><br><span class="line">     */</span><br><span class="line">    @Autowired</span><br><span class="line">    private WebApplicationContext webApplicationContext;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 所有测试方法执行之前执行该方法</span><br><span class="line">     */</span><br><span class="line">    @Before</span><br><span class="line">    public void before() &#123;</span><br><span class="line">        //获取mockmvc对象实例</span><br><span class="line">        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * 测试添加用户</span><br><span class="line">     * @throws Exception</span><br><span class="line">     */</span><br><span class="line">    @Test</span><br><span class="line">    public void testUserAdd() throws Exception</span><br><span class="line">    &#123;</span><br><span class="line">        mockMvc.perform(MockMvcRequestBuilders.post(&quot;/user/save&quot;)</span><br><span class="line">                .param(&quot;userName&quot;,&quot;yuqiyu&quot;)</span><br><span class="line">                .param(&quot;name&quot;,&quot;恒宇少年&quot;)</span><br><span class="line">                .param(&quot;age&quot;,&quot;23&quot;)</span><br><span class="line">        )</span><br><span class="line">                .andDo(MockMvcResultHandlers.log())</span><br><span class="line">                .andReturn();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>调用测试用例时会自动将参数保存到数据库，并且将用户编号发送到<code>RabbitMQ</code>服务端，而<code>RabbitMQ</code>根据交换配置以及队列配置转发消息到消费者实例。</p>
<h5 id="启动-rabbitmq-consumer"><a href="#启动-rabbitmq-consumer" class="headerlink" title="启动 rabbitmq-consumer"></a>启动 rabbitmq-consumer</h5><p>我们先来把<code>rabbitmq-consumer</code>项目启动，控制台输出启动日志如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">.....</span><br><span class="line">51.194  INFO 2340 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name &apos;rabbitConnectionFactory&apos; has been autodetected for JMX exposure</span><br><span class="line">2017-12-03 16:58:51.196  INFO 2340 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located managed bean &apos;rabbitConnectionFactory&apos;: registering with JMX server as MBean [org.springframework.amqp.rabbit.connection:name=rabbitConnectionFactory,type=CachingConnectionFactory]</span><br><span class="line">2017-12-03 16:58:51.216  INFO 2340 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483647</span><br><span class="line">2017-12-03 16:58:51.237  INFO 2340 --- [cTaskExecutor-1] o.s.a.r.c.CachingConnectionFactory       : Created new connection: rabbitConnectionFactory#443ff8ef:0/SimpleConnection@4369ac5c [delegate=amqp://guest@127.0.0.1:5672/, localPort= 62107]</span><br><span class="line">2017-12-03 16:58:51.287  INFO 2340 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 1111 (http)</span><br><span class="line">2017-12-03 16:58:51.290  INFO 2340 --- [           main] c.h.r.c.RabbitmqConsumerApplication      : Started RabbitmqConsumerApplication in 2.354 seconds (JVM running for 3.026)</span><br><span class="line">2017-12-03 16:58:51.290  INFO 2340 --- [           main] c.h.r.c.RabbitmqConsumerApplication      : 【【【【【消息队列-消息消费者启动成功.】】】】】</span><br></pre></td></tr></table></figure></p>
<p>该部分启动日志就是我们配置的<code>RabbitMQ</code>初始化信息，我们可以看到项目启动时会自动与配置的<code>RabbitMQ</code>进行关联：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[delegate=amqp://guest@127.0.0.1:5672/, localPort= 62107]</span><br></pre></td></tr></table></figure></p>
<h5 id="运行测试用例"><a href="#运行测试用例" class="headerlink" title="运行测试用例"></a>运行测试用例</h5><p>接下来我们执行<code>rabbitmq-provider</code>项目的测试用例，来查看控制台的输出内容如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">......</span><br><span class="line"> 回调id:e08f6d82-57bc-4c3f-9899-31c4b990c5be</span><br><span class="line">消息发送成功</span><br><span class="line">......</span><br></pre></td></tr></table></figure></p>
<p>已经可以正常的将消息发送到<code>RabbitMQ</code>服务端，并且接收到了回调通知，那么我们的<code>rabbitmq-consumer</code>项目是不是已经执行了消息的消费呢？我们打开<code>rabbitmq-consumer</code>控制台查看输出内容如下所示：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">用户：2，完成了注册</span><br></pre></td></tr></table></figure></p>
<p>看以看到已经可以成功的执行<code>UserConsumer</code>消息监听类内的监听方法逻辑，到这里消息队列路由一对一的方式已经讲解完了。</p>
<h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>本章主要讲解了<code>RabbitMQ</code>在不同操作系统下的安装方式，以及通过三个子模块形象的展示了消息的分布式处理，整体流程：rabbitmq-provider -&gt; <code>RabbitMQ</code>服务端 -&gt; rabbitmq-consumer，消息的转发是非常快的，<code>RabbitMQ</code>在收到消息后就会检索当前服务端是否存在该消息的消费者，如果存在将会马上将消息转发。</p>
<p>本章源码已经上传到码云：<br>SpringBoot配套源码地址：<a href="https://gitee.com/hengboy/spring-boot-chapter" target="_blank" rel="noopener">https://gitee.com/hengboy/spring-boot-chapter</a><br>SpringCloud配套源码地址：<a href="https://gitee.com/hengboy/spring-cloud-chapter" target="_blank" rel="noopener">https://gitee.com/hengboy/spring-cloud-chapter</a><br>SpringBoot相关系列文章请访问：<a href="http://www.jianshu.com/p/9a08417e4e84" target="_blank" rel="noopener">目录：SpringBoot学习目录</a><br>QueryDSL相关系列文章请访问：<a href="http://www.jianshu.com/p/99a5ec5c3bd5" target="_blank" rel="noopener">QueryDSL通用查询框架学习目录</a><br>SpringDataJPA相关系列文章请访问：<a href="http://www.jianshu.com/p/615ed9c1fe84" target="_blank" rel="noopener">目录：SpringDataJPA学习目录</a><br>SpringBoot相关文章请访问：<a href="http://www.jianshu.com/p/9a08417e4e84" target="_blank" rel="noopener">目录：SpringBoot学习目录</a>，感谢阅读！<br>欢迎加入QQ技术交流群，共同进步。<br><img src="http://upload-images.jianshu.io/upload_images/4461954-d80b777ca38632ba.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="QQ技术交流群"></p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">


    <div class="bdsharebuttonbox">
    <a href="#" class="bds_more" data-cmd="more">分享到：</a>
    <a href="#" class="bds_qzone" data-cmd="qzone" title="分享到QQ空间">QQ空间</a>
    <a href="#" class="bds_tsina" data-cmd="tsina" title="分享到新浪微博">新浪微博</a>
    <a href="#" class="bds_tqq" data-cmd="tqq" title="分享到腾讯微博">腾讯微博</a>
    <a href="#" class="bds_renren" data-cmd="renren" title="分享到人人网">人人网</a>
    <a href="#" class="bds_weixin" data-cmd="weixin" title="分享到微信">微信</a>
</div>
<script>
window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{"bdSize":16}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];
</script>
<style>
    .bdshare_popup_box {
        border-radius: 4px;
        border: #e1e1e1 solid 1px;
    }
    .bdshare-button-style0-16 a,
    .bdshare-button-style0-16 .bds_more {
        padding-left: 20px;
        margin: 6px 10px 6px 0;
    }
    .bdshare_dialog_list a,
    .bdshare_popup_list a,
    .bdshare_popup_bottom a {
        font-family: 'Microsoft Yahei';
    }
    .bdshare_popup_top {
        display: none;
    }
    .bdshare_popup_bottom {
        height: auto;
        padding: 5px;
    }
</style>


</div>

            
    

        </footer>
    </div>
    
        
<nav id="article-nav">
    
        <a href="/spring-boot-chapter-42/" id="article-nav-newer" class="article-nav-link-wrap">
            <strong class="article-nav-caption">上一篇</strong>
            <div class="article-nav-title">
                
                    第四十二章： 基于SpringBoot &amp; RabbitMQ完成DirectExchange分布式消息多消费者消费
                
            </div>
        </a>
    
    
        <a href="/spring-boot-chapter-40/" id="article-nav-older" class="article-nav-link-wrap">
            <strong class="article-nav-caption">下一篇</strong>
            <div class="article-nav-title">第四十章：基于SpringBoot &amp; Quartz完成定时任务分布式多节点负载持久化</div>
        </a>
    
</nav>


    
</article>


    
    

</section>
            
			
				
<aside id="sidebar">
   
        
    <div class="widget-wrap">
        <h3 class="widget-title">最新文章</h3>
        <div class="widget">
            <ul id="recent-post" class="no-thumbnail">
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-52/" class="title">第五十二章：基于SpringBoot2使用Rest访问MongoDB数据</a></p>
                            <p class="item-date"><time datetime="2018-04-21T16:00:00.000Z" itemprop="datePublished">2018-04-22</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-51/" class="title">第五十一章：基于SpringBoot2 &amp; MongoDB完成自动化集成</a></p>
                            <p class="item-date"><time datetime="2018-04-15T16:00:00.000Z" itemprop="datePublished">2018-04-16</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-50/" class="title">第五十章：SpringBoot2.0新特性 - 岂止至今最简单redis缓存集成</a></p>
                            <p class="item-date"><time datetime="2018-04-14T16:00:00.000Z" itemprop="datePublished">2018-04-15</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-49/" class="title">第四十九章：SpringBoot2.0新特性 - 你get到WebMvcConfigurer两种配置方式了吗？</a></p>
                            <p class="item-date"><time datetime="2018-03-16T16:00:00.000Z" itemprop="datePublished">2018-03-17</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a></p>
                            <p class="item-title"><a href="/spring-boot-chapter-48/" class="title">第四十八章：SpringBoot2.0新特性 - RabbitMQ信任package设置</a></p>
                            <p class="item-date"><time datetime="2018-03-12T16:00:00.000Z" itemprop="datePublished">2018-03-13</time></p>
                        </div>
                    </li>
                
            </ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">分类</h3>
        <div class="widget">
            <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/QueryDSL-核心技术/">QueryDSL 核心技术</a><span class="category-list-count">7</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/SpringBoot-核心技术/">SpringBoot 核心技术</a><span class="category-list-count">36</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">归档</h3>
        <div class="widget">
            <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/04/">四月 2018</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/03/">三月 2018</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/01/">一月 2018</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/12/">十二月 2017</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/11/">十一月 2017</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/10/">十月 2017</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/09/">九月 2017</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/08/">八月 2017</a><span class="archive-list-count">4</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/07/">七月 2017</a><span class="archive-list-count">9</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/06/">六月 2017</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/05/">五月 2017</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/04/">四月 2017</a><span class="archive-list-count">5</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">标签</h3>
        <div class="widget">
            <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/QueryDSL/">QueryDSL</a><span class="tag-list-count">7</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/SpringBoot/">SpringBoot</a><span class="tag-list-count">43</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">标签云</h3>
        <div class="widget tagcloud">
            <a href="/tags/QueryDSL/" style="font-size: 10px;">QueryDSL</a> <a href="/tags/SpringBoot/" style="font-size: 20px;">SpringBoot</a>
        </div>
    </div>

    
        
    <div class="widget-wrap widget-list">
        <h3 class="widget-title">链接</h3>
        <div class="widget">
            <ul>
                
                    <li>
     				<a href="http://hexo.io" target="_blank">Hexo</a>
					</li>
                
            </ul>
        </div>
    </div>


    
    <div id="toTop" class="fa fa-angle-up"></div>
</aside>

				
        </div>
        <!--引入不蒜子-->
<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<footer id="footer">
    <div class="outer">
        <div id="footer-info" class="inner">
            <span  id="busuanzi_container_site_pv">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
            &copy; 2017 - 2018 恒宇少年 - 版权所有<br>
        </div>
    </div>
</footer>

        


    
        <script src="/libs/lightgallery/js/lightgallery.min.js"></script>
        <script src="/libs/lightgallery/js/lg-thumbnail.min.js"></script>
        <script src="/libs/lightgallery/js/lg-pager.min.js"></script>
        <script src="/libs/lightgallery/js/lg-autoplay.min.js"></script>
        <script src="/libs/lightgallery/js/lg-fullscreen.min.js"></script>
        <script src="/libs/lightgallery/js/lg-zoom.min.js"></script>
        <script src="/libs/lightgallery/js/lg-hash.min.js"></script>
        <script src="/libs/lightgallery/js/lg-share.min.js"></script>
        <script src="/libs/lightgallery/js/lg-video.min.js"></script>
    
    
        <script src="/libs/justified-gallery/jquery.justifiedGallery.min.js"></script>
    
    



<!-- Custom Scripts -->
<script src="/js/main.js"></script>

    </div>
</body>
</html>